webpack 构建优化
1. 开发阶段
热更新
它允许在运行时更新所有类型的模块,而无需完全刷新。
module.exports = {
plugins: [new webpack.HotModuleReplacementPlugin()],
devServer: {
hot: true,
},
}
2. 构建阶段
几个大方向入手:缓存、多核、抽离以及拆分
缓存
babel-loader将 loader
的编译结果写入硬盘缓存,再次构建如果文件没有发生变化则会直接拉取缓存。可以通过设置 cacheDirectory
来开启缓存。
它所做的事情,就是 babel-loader 开启 cache 后做的事情
uglifyjs-webpack-plugin代码压缩阶段,也可以通过缓存解决大部分问题。我们可以通过开启 cache
配置开启我们的缓存功能,也可以通过开启 parallel
开启多核编译功能。
代码示例:
module.exports = {
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
}),
],
},
}
多核构建
可能在 webpack 中已经内置了该功能,有待继续研究!
抽离
对于一些不常变更的静态依赖,比如我们项目中常见的 React 全家桶、lodash 等等,我们不希望这些依赖被集成进每一次构建逻辑中,因此,我们会设法将这些静态依赖从每一次的构建逻辑中抽离出去,以提升我们每次构建的构建效率。
常见的方案有两种
在首次构建时候就将这些静态依赖单独打包,后续只需要引用这个早就被打好的静态依赖包即可,有点类似“预编译”的概念
我们将这些不需要打包的静态资源从构建逻辑中剔除出去,而使用 CDN 的方式,去引用它们。
拆分
入口拆分在一个多页应用中,有多个 entry
的前提下,有时候我们只是更改了一个 entry
下的文件,但是却要对所有 entry
执行一遍构建,优化方案
-
每一个子模块都被拆分成了一个单独的仓库中,单独构建
-
集群编译
这里的集群当然不是指我们的真实物理机,而是我们的 docker。其原理就是将单个 entry 剥离出来维护一个独立的构建流程,并在一个容器内执行,待构建完成后,将生成文件打进指定目录。
为什么能这么做呢?因为我们知道,webpack 会将一个 entry 视为一个 chunk,并在最后生成文件时,将 chunk 单独生成一个文件,
在 Webpack4 中移除了我们此前常用的 CommonsChunkPlugin
插件,取而代之的是 splitChunks
。 splitChunks
的默认配置已经足够我们日常使用,没有特殊需求可以不必特意处理。 我们此处的配置如下(生产环境):
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
// 可能会增加构建时间
// styles: {
// name: 'index',
// test: /.stylus|css$/,
// chunks: 'all',
// enforce: true
// }
}
}
}
其中,commons 部分的作用是分离出 node_modules 中引入的模块,styles 部分则是合并 CSS 文件。
优化模块查找路径
module.exports = {
exclude: /node_modules/, // 排除不处理的目录
include: path.resolve(__dirname, 'src') // 精确指定要处理的目录
resolve: {
// 用于配置 webpack 去哪些目录下寻找第三方模块
modules: [path.resolve(__dirname, 'node_modules')],
// 过别名来把原导入路径映射成一个新的导入路径,减少耗时的递归解析操作
alias: {
'api': resolve('src/api') // 创建别名
}
}
}
3. 构建结果
- 区分构建环境。webpack 生产环境的构建自带一些优化。
- 压缩。包括 js、css 代码,以及 gzip 压缩。
- 开启 tree-shaking。
- 注意 source-map 类型。生产环境一般不需要。
4. 构建打点
speed-measure-webpack-plugin它能够测量出在你的构建过程中,每一个 Loader 和 Plugin 的执行时长,官方给出的效果图是下面这样:
5. 构建分析
输出 Webpack 构建信息的.json 文件webpack --profile --json > stats.json
有两种方式:
- 通过可视化分析工具,是个在线 Web 应用,上传 stats.json 文件就可以
6. 其他
progress-bar-webpack-plugin能为你展示构建进度的 Plugin。效果图:
webpack-build-notifier在你构建完成时 ,能够像微信、Lark 这样的 APP 弹出消息的方式,提示你构建已经完成了。效果图:
webpack-dashboard如果你对 webpack 原始的构建输出不满意的话,也可以使用这样一款 Plugin 来优化你的输出界面。效果图